"use strict";
importScripts("psl.min.js", "common.js");

let _whiteList = null;
let _lastTabId = null;

async function getWhiteList() {
	let result = await chrome.storage.local.get("whitelist");
	_whiteList = result.whitelist;
	if (!_whiteList) {
		_whiteList = "^http[s]?://([\\w\\-]+\\.)*gov\\.cn(/.*)?$\n^http[s]?://([\\w\\-]+\\.)*360\\.(cn|net|com)(/.*)?$";
	}
	return _whiteList;
}

async function setWhiteList(data) {
	_whiteList = data;
	return await chrome.storage.local.set({whitelist: data});
}

async function updateBrowserStatus() {
	let c = await getDataCount();
	chrome.action.setTitle({title: "回收站(" + c + ")"});
	chrome.action.setIcon(c > 0 ? {path: "/images/ico54-012.png"} : {path: "/images/ico55-012.png"});
}

async function updateData() {
	await setRootJson(_rootJson);
	await updateBrowserStatus();
	chrome.tabs.query({}, function(tabs) {
		for (let tab of tabs) {
			chrome.tabs.sendMessage(tab.id, {name: "update-data"}).catch(error => {
				showError("update-data", error);
			});
		}
	});
}

function main() {
	chrome.contextMenus.removeAll(function() {
		let myContexts = ["page", "frame", "selection", "link", "editable", "image", "video", "audio"];
		chrome.contextMenus.create({
			title: "回收站",
			id: "recycle-bin",
			documentUrlPatterns: ["http://*/*", "https://*/*", "file:///*", "ftp://*/*", "urn:*"],
			contexts: myContexts
		});
		chrome.contextMenus.create({
			title: "进入左键选择状态",
			id: "enter-selecting",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		chrome.contextMenus.create({
			id: "separator1",
			parentId: "recycle-bin",
			contexts: myContexts,
			type: "separator"
		});
		chrome.contextMenus.create({
			title: "移入回收站",
			id: "throw-into-the-recyclebin",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		chrome.contextMenus.create({
			title: "移入全局回收站",
			id: "throw-into-the-global-recyclebin",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		chrome.contextMenus.create({
			title: "移入回收站并举报",
			id: "throw-into-the-recyclebin-and-report",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		chrome.contextMenus.create({
			id: "separator2",
			parentId: "recycle-bin",
			contexts: myContexts,
			type: "separator"
		});
		chrome.contextMenus.create({
			title: "打开选项页面",
			id: "open-options-page",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		chrome.contextMenus.create({
			id: "separator3",
			parentId: "recycle-bin",
			contexts: myContexts,
			type: "separator"
		});
		chrome.contextMenus.create({
			title: "清空回收站",
			id: "clear-all-data",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		chrome.contextMenus.create({
			title: "撤销移入操作",
			id: "pop-item",
			parentId: "recycle-bin",
			contexts: myContexts
		});
		
		chrome.contextMenus.onClicked.addListener(async function(info, tab) {
			switch (info.menuItemId) {
			case "open-options-page":
				chrome.runtime.openOptionsPage();
				break;
			case "enter-selecting":
				_is_selecting = true;
				await updateSelectingTab(tab.id);
				break;
			default:
				chrome.tabs.sendMessage(tab.id, {name: info.menuItemId}, {frameId: info.frameId}).catch(error => {
					showError(info.menuItemId, error);
				});
				break;
			}
		});
	});

	chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
		console.log("onMessage: " + message.name);
		switch (message.name) {
		case "get-data":
			(async () => {
				let rj = await getRootJson();
				sendResponse({rootJson: rj});
			})();
			break;
		case "set-data":
			(async () => {
				_rootJson = message.data;
				await updateData();
				sendResponse();
			})();
			break;
		case "clear-all-data":
			(async () => {
				let rj2 = await getRootJson();
				let arrdata = rj2.data;
				let i = arrdata.length - 1;
				while (i >= 0) {
					if (!hasOption(arrdata[i], "prevent_delete")) {
						arrdata.splice(i, 1);
					}
					i--;
				}
				await updateData();
				chrome.tabs.query({}, function(tabs) {
					for (let tab of tabs) {
						chrome.tabs.sendMessage(tab.id, {name: "clear-data"}).catch(error => {
							showError("clear-data", error);
						});
					}
				});
				sendResponse();
			})();
			break;
		case "update-options":
			(async () => {
				chrome.tabs.query({}, function(tabs) {
					for (let tab of tabs) {
						chrome.tabs.sendMessage(tab.id, {name: "update-options"}).catch(error => {
							showError("update-options", error);
						});
					}
				});
				sendResponse();
			})();
			break;
		case "push-item":
			(async () => {
				message.data.page_url = sender.tab.url;
				
				let blnDoPush = message.doPush;
				let wl = await getWhiteList();
				let blnInWhiteList = false;
				for (let pattern of wl.split("\n")) {
					if (pattern == "") {
						continue;
					}
					let objRegExp = new RegExp(pattern, "i");
					if (objRegExp.test(message.data.frame_url) || objRegExp.test(message.data.page_url)) {
						blnInWhiteList = true;
						break;
					}
				}

				if (blnInWhiteList) {
					blnDoPush = false;
				}

				if (blnDoPush) {
					let rj3 = await getRootJson();
					rj3.data.push(message.data);
					await updateData();
					chrome.tabs.query({}, function(tabs) {
						for (let tab of tabs) {
							if (!isObjEqual(tab, sender.tab)) {
								chrome.tabs.sendMessage(tab.id, {name: "hide-item", data: message.data}).catch(error => {
									showError("hide-item", error);
								});
							}
						}
					});
				}

				sendResponse({data: message.data, doPush: blnDoPush, inWhiteList: blnInWhiteList});
			})();
			break;
		case "pop-item":
			(async () => {
				let rj5 = await getRootJson();
				let arrdata5 = rj5.data;
				let j = arrdata5.length - 1;
				while (j >= 0) {
					if (!hasOption(arrdata5[j], "prevent_delete")) {
						break;
					}
					j--;
				}
				if (j >= 0) {
					let arr = arrdata5.splice(j, 1);
					await updateData();
					for (let item of arr) {
						chrome.tabs.query({}, function(tabs) {
							for (let tab of tabs) {
								chrome.tabs.sendMessage(tab.id, {name: "restore-item", data: item}).catch(error => {
									showError("restore-item", error);
								});
							}
						});
					}
				}
				sendResponse({count: arrdata5.length});
			})();
			break;
		case "get-data-count":
			(async () => {
				let c = await getDataCount();
				sendResponse({count: c});
			})();
			break;
		case "get-whitelist":
			(async () => {
				let wl2 = await getWhiteList();
				sendResponse({whitelist: wl2});
			})();
			break;
		case "set-whitelist":
			(async () => {
				await setWhiteList(message.whitelist);
				sendResponse();
			})();
			break;
		case "capture-page":
			(async () => {
				chrome.tabs.captureVisibleTab(null, {format: "png"}, function(data) {
					chrome.storage.local.set({capture: {jsonData: message.data, imageData: data}}, function() {
						chrome.runtime.openOptionsPage();
						sendResponse();
					});
				});
			})();
			break;
		case "toggle-selecting":
			(async () => {
				console.log("receive toggle-selecting message;")
				let tabId = 0;
				_is_selecting = !_is_selecting;	
				if (sender.tab) {
					tabId = sender.tab.id;
				} else {
					const [tab] = await chrome.tabs.query({
						active: true,
						currentWindow: true
					});
					tabId = tab.id;
				}
				console.log(tabId)
				await updateSelectingTab(tabId);
				sendResponse(_is_selecting);
			})();
			break;
		case "get-selecting":
			(async () => {
				sendResponse({is_selecting: _is_selecting});
			})();
			break;
		}
		
		return true;
	});

	async function updateSelectingTab(tabId) {
		const selecting_css = `*:not(:has(*:hover)):hover {outline: 3px solid #00A2E888 !important; outline-offset: -3px !important; background-color: #99D9EA88 !important;}`;
		console.log("_is_selecting: " + _is_selecting);
		if (_is_selecting) {
			await chrome.scripting.insertCSS({
				css: selecting_css,
				origin: "USER",
				target: {
					allFrames: true,
					tabId: tabId
				}
			}).catch(error => {
				_is_selecting = false;
				showError("updateSelectingTab", error);
			});	
		} else {
			await chrome.scripting.removeCSS({
				css: selecting_css,
				origin: "USER",
				target: {
					allFrames: true,
					tabId: tabId
				}
			}).catch(error => {
				showError("updateSelectingTab", error);
			});
		}
		await chrome.tabs.sendMessage(tabId, {name: "toggle-selecting", is_selecting: _is_selecting}).catch(error => {
			showError("updateSelectingTab", error);
		});	
	}

	updateBrowserStatus();
	
	chrome.webNavigation.onDOMContentLoaded.addListener(function(details) {
		if (details.frameId === 0) {
			chrome.tabs.sendMessage(details.tabId, {name: "init-page", data: "回收站: 已加载."}, {frameId: details.frameId}).catch(error => {
				showError("init-page", error);
			});
		}
	}, {url: [{schemes: ["http", "https"]}]});
	
	chrome.tabs.onActivated.addListener(async function(activeInfo) {
		if (_lastTabId && _is_selecting) {
			_is_selecting = false;
			await updateSelectingTab(_lastTabId);
		}
		_lastTabId = activeInfo.tabId;
	});
}

main();
